﻿/*
 * GridData
 * 
 * initial implementation : 20.9.2008
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see Petra.Gis.License.txt
 */
using System;
using System.IO;
using System.Windows.Threading;
using System.Windows.Media.Imaging;
using System.Collections.Generic;

using Petra.Gis.Geometry.Support;
using Petra.Gis.Geometry.GridSupport;
using Petra.Gis.ImagingServices;




namespace Petra.Gis.DataServices
{

  
  public class GridData : GridDataBase
  {




    /// <summary>
    /// GridData without decoder constructor for download images
    /// </summary>
    /// <param name="data">BitmapSource with data from remote server</param>
    /// <param name="bounds">projection bounds of GridData</param>
    /// <param name="dataLocation">Uri to Grid data</param>
    protected GridData(BitmapSource data, BoundingBox bounds, Uri dataLocation)
      :base()
    {
      _bounds = bounds;
      this.DataLocation = dataLocation;

      _frames.Add(new GridFrame(data, bounds));

    }


#if !SILVERLIGHT

    /// <summary>
    /// GridData with WPF decoder constructor. NOT available on silverlight
    /// </summary>
    /// <param name="decoder">WPF decoder</param>
    /// <param name="bounds">projection bounds of GridData</param>
    /// <param name="dataLocation">Uri to Grid data</param>
    protected GridData(BitmapDecoder decoder, BoundingBox bounds, Uri dataLocation)
      :base()
    {
      _bounds = bounds;
      this.DataLocation = dataLocation;

      //foreach (BitmapFrame f in decoder.Frames)
      foreach (BitmapSource f in decoder.Frames)
        _frames.Add(new GridFrame(f, bounds));

    }





    /// <summary>
    /// GridData with Petra.Gis.Imaging.SimpleBitmapDecoder decoder 
    /// </summary>
    /// <param name="decoder">Petra.Gis.Imaging.SimpleBitmapDecoder</param>
    /// <param name="bounds">projection bounds of GridData</param>
    /// <param name="dataLocation">Uri to Grid data</param>
    protected GridData(GridBitmapDecoderBase decoder, BoundingBox bounds, Uri dataLocation)
      : base()
    {
      _bounds = bounds;
      this.DataLocation = dataLocation;

      //foreach (BitmapFrame f in decoder.Frames)
      foreach (BitmapSource f in decoder.Frames)
        _frames.Add(new GridFrame(f, bounds));

    }


#endif

    //public override BoundingBox GetEnvelope()
    //{
    //  return _bounds ;
    //}






    public override bool IsGridWithOverviews
    {
      //todo: perform more tests to determine....
      get
      {
        if (_frames.Count > 1)
          return true;
        else
          return false;
      }
    }




    /// <summary>
    /// creates new instance of GridData from Uri and BoundingBox.
    /// </summary>
    /// <param name="fileUri">fileUri</param>
    /// <param name="dataBounds">grid projection extent</param>
    /// <returns>new GridData when decoder found or null when decoder for grid data not available</returns>
    public static GridDataBase Create(Uri fileUri, BoundingBox dataBounds)
    {
      if (fileUri.IsFile)
      {
#if !SILVERLIGHT
        //when filepath create image using decoder
        try
        {
          return createFromFilePath(fileUri, dataBounds);
        }
        catch
        {
          return null;
        }
#else
        throw new NotSupportedException();
#endif
      }
      else
      { 
        //when URI is not file based try invoke some image directly from URL
        //this is available for silverlight for PNG, JPG file format
        //throw new NotImplementedException();
        return new GridData(new BitmapImage(fileUri), dataBounds, fileUri);
      }

    }



#if !SILVERLIGHT

    private static GridDataBase createFromFilePath(Uri fileUri, BoundingBox dataBounds)
    {

      //prepare to get decoder...
      string ext = Path.GetExtension(fileUri.LocalPath).ToLower();
      CustomComponent tmp = null;

      if (Environment.Components["GridDataDecoders"].Count == 0)
        return null;

      //search through available decoders
      foreach (KeyValuePair<string, CustomComponent> kvp in Environment.Components["GridDataDecoders"])
        if (kvp.Key.ToLower() == ext)
        {
          tmp = kvp.Value;
          break;
        }

      if (tmp == null)
        return null; //not found

      //try create decoder
      //each decoder must support default ctor (String filename, BitmapCreateOptions, BitmapCacheOption)
      DispatcherObject bd = (DispatcherObject)tmp.CreateInstance(
        new object[]
        {
          fileUri, BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnDemand
        }
      );

      if (bd is BitmapDecoder)
        return new GridData((BitmapDecoder)bd, dataBounds, fileUri);

      else if (bd is GridBitmapDecoderBase)
        return new GridData((GridBitmapDecoderBase)bd, dataBounds, fileUri);

      else
        return null;

    }

#endif //SILVERLIGHT

  }
}
